/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ru.apertum.diasled.rxtx;

import gnu.io.SerialPortEvent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.swing.Timer;
import ru.apertum.diasled.cfg.Configuration;
import ru.evgenic.rxtx.serialPort.IReceiveListener;
import ru.evgenic.rxtx.serialPort.IReceiveStreamListener;
import ru.evgenic.rxtx.serialPort.ISerialPort;
import ru.evgenic.rxtx.serialPort.RxtxSerialPort;

/**
 *
 * @author Evgeniy Egorov
 */
public class EasyExp {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws Exception {
        // в конструктор передать название порта, например COM1 под win или /dev/ttyS0 под nix
        final ISerialPort port = new RxtxSerialPort("COM3");
        port.setSpeed(921600);
        port.setDataBits(8);
        port.setParity(0);
        port.setStopBits(1);

        final CyclicBarrier cb = new CyclicBarrier(2);

        final ArrayList<byte[]> exch = new ArrayList<>();

        port.bind(new IReceiveListener() {

            @Override
            public void actionPerformed(SerialPortEvent event, byte[] data) {
                exch.clear();
                exch.add(data);
                System.out.println("Receive message from Port: " + data.length + " bytes");
                try {
                    cb.await();
                } catch (InterruptedException | BrokenBarrierException ex) {
                    System.err.println(ex);
                }
            }

            @Override
            public void actionPerformed(SerialPortEvent event) {
                System.out.println(port.getName() + " " + event.getEventType());
                /*
                try {
                cb.await();
                } catch (InterruptedException | BrokenBarrierException ex) {
                System.err.println(ex);
                }
                 * 
                 */
            }
        });





        byte[] request = new byte[1];

        // Запрос на определение железки        
        System.out.println("Запрос на определение железки");
        request[0] = (byte) 0xf0;
        exch.clear();
        port.send(request);

        try {
            cb.await(1000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException | BrokenBarrierException | TimeoutException ex) {
            System.err.println("Прорыв барьера 1");
        }

        byte[] rec = exch.get(0);
        for (byte b : rec) {
            System.out.println(" =" + (b & 255));
        }




        // Очистка железки        
        System.out.println("Очистка железки");

        cb.reset();
        request = new byte[5];
        request[0] = (byte) 0x08;
        request[1] = (byte) 0x00;
        request[2] = (byte) 0x00;
        request[3] = (byte) 0x00;
        request[4] = (byte) 0x00;
        exch.clear();
        port.send(request);

        try {
            cb.await(1000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException | BrokenBarrierException | TimeoutException ex) {
            System.err.println("Прорыв барьера очистки");
        }





        // Запрос на определение конфигурации
        System.out.println("Запрос на определение конфигурации");
        cb.reset();
        request = new byte[1];

        request[0] = (byte) 0x10;
        exch.clear();
        port.send(request);

        try {
            cb.await(1000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException | BrokenBarrierException | TimeoutException ex) {
            System.err.println("Прорыв барьера 2");
        }

        rec = exch.get(0);
        for (byte b : rec) {
            System.out.println(" =" + (b & 255));
        }

        Configuration cfg = Configuration.load(new File("config/w.vit"));


        final ByteBuffer buffer = ByteBuffer.allocate(512 * 2);
        final byte[] ret = new byte[512 * 2];
        int i = 0;
        for (short sh : cfg.getCoefs()) {
            System.out.print(" " + sh);
            buffer.putShort(sh);


            ret[i * 2] = (byte) (sh & 0xff);
            ret[i * 2 + 1] = (byte) ((sh >> 8) & 0xff);
            i++;
        }
        System.out.println();
        for (byte b : buffer.array()) {
            System.out.print(" " + b);
        }
        System.out.println();
        //  Buffer bb = buffer.flip();
        for (byte b : ret) {
            System.out.print(" " + b);
        }
        System.out.println();

        // Отправка коэф. смещения и усиления
        System.out.println("Отправка коэф. смещения и усиления");
        cb.reset();
        request[0] = (byte) 0x03;
        exch.clear();
        port.send(request);

        Thread.sleep(50);

        port.send(ret);


        try {
            cb.await(1000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException | BrokenBarrierException | TimeoutException ex) {
            System.err.println("Прорыв барьера Отправки коэфициентов");
        }


        // Начало эксперимента
        System.out.println("Начало эксперимента");
        request = new byte[6];
        cb.reset();
        request[0] = (byte) 0x04;
        /*
        #define SLED_EXPERIMENT_DATA    0x01
        #define SLED_RAW_DATA           0x02
        #define SLED_DEBUG_DATA         0x03
         */
        request[1] = (byte) 0x01;


        int value = 200;
        request[5] = (byte) (value >>> 24);
        request[4] = (byte) (value >>> 16);
        request[3] = (byte) (value >>> 8);
        request[2] = (byte) value;

        exch.clear();


        final ArrayList<InputStream> exchEx = new ArrayList<>();
        port.setReceiveStreamListeners(new IReceiveStreamListener() {

            int i = 0;
            @Override
            public void actionPerformed(SerialPortEvent event, InputStream in) {
                if(i++>0){
                    return;
                }
                exchEx.add(in);
               // System.out.println("1 Экспериментальные данные from Port:");
                try {
                    cb.await();
                } catch (InterruptedException | BrokenBarrierException ex) {
                    System.err.println(ex);
                }
            }

            @Override
            public void actionPerformed(SerialPortEvent event) {
                System.out.println("Событие приема данных " + port.getName() + " " + event.getEventType());
            }
        });

        System.out.print("команда на эксперимент  ");
        for (byte b : request) {
            System.out.print(" " + b);
        }
        System.out.println();

        port.send(request);



        try {
            cb.await(1000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException | BrokenBarrierException | TimeoutException ex) {
            System.err.println("Прорыв барьера 4");
        }

        final Timer t = new Timer(1000, new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                
                System.out.println("STOP");
                byte[] bb = new byte[1];
                bb[0] = (byte) 0x05;
                try {
                    port.send(bb);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                
            }
        });
      //  t.start();

        final InputStream inputStream = exchEx.get(0);

        // read data
        byte[] res = new byte[0];
        int ate = 0;
        int i255 = 0;
        System.out.println("РЕЗУЛЬТАТ");
        while (inputStream.available() != 0 || ate < 4) {
            if (inputStream.available() == 0) {
                ate++;
                Thread.sleep(125);
            } else {
                ate = 0;

                final byte[] sb = new byte[inputStream.available()];
                inputStream.read(sb);

                for (byte b : sb) {
                    System.out.print(" " + b);
                    if (i255 < 256) {
                        i255++;
                    } else {
                        i255 = 0;
                        System.out.println();
                    }

                }
                final byte[] n = Arrays.copyOf(res, sb.length + res.length);
                System.arraycopy(sb, 0, n, n.length - sb.length, sb.length);
                res = Arrays.copyOf(n, n.length);
            }
            Thread.sleep(25);

        }

        System.out.println();
        System.out.println(" КОНЕЦ " + res.length);



        port.free();
    }
}
